/*
 * Copyright 2010 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.lightframework.jamwiki.utils;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.jamwiki.DataAccessException;
import org.jamwiki.Environment;
import org.jamwiki.WikiBase;
import org.jamwiki.WikiException;
import org.jamwiki.db.WikiDatabase;
import org.jamwiki.model.Topic;
import org.jamwiki.model.TopicVersion;
import org.jamwiki.model.VirtualWiki;
import org.jamwiki.model.WikiUser;
import org.jamwiki.utils.Utilities;
import org.jamwiki.utils.WikiLogger;
import org.lightframework.jamwiki.RuntimeWikiException;
import org.lightframework.jamwiki.servlets.SetupServletEx;

/**
 * @author fenghm(live.fenghm@gmail.com)
 */
public final class WikiDatabaseEx {
	
	private static final WikiLogger logger = WikiLogger.getLogger(WikiDatabaseEx.class.getName());
	
	private static List<String> pages;
	
	static{
		try {
	        pages = ClassUtils.findAllResourceNames(SetupServletEx.class.getClassLoader(), WikiDatabase.SPECIAL_PAGE_DIR, false);
        } catch (IOException e) {
        	throw new RuntimeWikiException(e.getMessage(),e);
        }
	}

	public static void createSpecialWikis(HttpServletRequest request,Locale locale,WikiUser user) throws WikiException,DataAccessException,IOException{
		String name =org.lightframework.jamwiki.model.VirtualWiki.SPECIAL_WIKI_NAME;
		//create virtual wiki
		VirtualWiki virtualWiki = new VirtualWiki();
		virtualWiki.setName(name);
		virtualWiki.setDefaultTopicName(Environment.getValue(Environment.PROP_BASE_DEFAULT_TOPIC));
		WikiBase.getDataHandler().writeVirtualWiki(virtualWiki);		
		
		//create default topics
		List<String> pages = ClassUtils.findAllResourceNames(SetupServletEx.class.getClassLoader(), "wikis.special", false);
		for(String page : pages){
			if(page.endsWith(".txt")){
				String topicName = page.substring(0,page.length() - 4);
				WikiDatabaseEx.setupDefaultPage(locale, virtualWiki.getName(), "wikis/" + name, topicName, user, true);
			}
		}		
	}	
	
	public static boolean isDefaultPage(String topicName){
		topicName = topicName.replaceAll(":", "/") + ".txt";
        for(String page : pages){
        	if(page.equals(topicName)){
        		return true;
        	}
        }
        return false;
	}
	
	public static void setupDefaultPages(Locale locale,String wikiName,WikiUser user) throws IOException,DataAccessException, WikiException{
		//remove aleady created pages by jamwiki
		pages.remove("BottomArea.txt");
		pages.remove("LeftMenu.txt");
		pages.remove("StartingPoints.txt");
		pages.remove("StyleSheet.txt");
		
		for(String page : pages){
			if(page.endsWith(".txt")){
				String topicName = page.substring(0,page.length() - 4);
				setupDefaultPage(locale,wikiName,WikiDatabase.SPECIAL_PAGE_DIR,topicName,user,true);
			}
		}
	}	
	
	public static void setupDefaultPage(Locale locale,String wiki,String pkg,String topicName,WikiUser user,boolean adminOnly) throws DataAccessException,WikiException{
		logger.info("Setting up special page " + wiki + " / " + topicName);
		if (user == null) {
			throw new IllegalArgumentException("Cannot pass null WikiUser object to setupSpecialPage");
		}
		String contents = null;
		try {
			contents = readPageContent(locale, pkg, topicName);
		} catch (IOException e) {
			throw new DataAccessException(e);
		}
		
		if(topicName.indexOf("\\") > 0){
			topicName = topicName.replaceAll("\\\\", ":");
		}else if(topicName.indexOf("/") > 0){
			topicName = topicName.replaceAll("/", ":");
		}else{
			topicName = topicName.replaceFirst("_",":");	
		}
		
		Topic topic = new Topic(wiki, topicName);
		topic.setTopicContent(contents);
		topic.setAdminOnly(adminOnly);
		int charactersChanged = StringUtils.length(contents);
		// FIXME - hard coding
		TopicVersion topicVersion = new TopicVersion(user, user.getLastLoginIpAddress(), "Automatically created by system setup", contents, charactersChanged);
		// FIXME - it is not connection-safe to parse for metadata since we are already holding a connection
		// ParserOutput parserOutput = ParserUtil.parserOutput(topic.getTopicContent(), virtualWiki, topicName);
		// WikiBase.getDataHandler().writeTopic(topic, topicVersion, parserOutput.getCategories(), parserOutput.getLinks());
		WikiBase.getDataHandler().writeTopic(topic, topicVersion, null, null);		
	}
	
	public static String readPageContent(Locale locale,String pkg,String topicName) throws IOException{
		String contents = null;
		String filename = null;
		String language = null;
		String country = null;
		if (locale != null) {
			language = locale.getLanguage();
			country = locale.getCountry();
		}
		String subdirectory = "";
		if (!StringUtils.isBlank(language) && !StringUtils.isBlank(country)) {
			try {
				subdirectory = language + "_" + country;
				filename = "/" + pkg  + "/" + subdirectory + "/" + topicName + ".txt";
				contents = Utilities.readFile(filename);
			} catch (IOException e) {
				logger.info("No locale-specific file is available for " + filename + ", checking for a language-specific version.");
			}
		}
		if (contents == null && !StringUtils.isBlank(language)) {
			try {
				subdirectory = language;
				filename = "/" + pkg  + "/" + subdirectory + "/" + topicName + ".txt";
				contents = Utilities.readFile(filename);
			} catch (IOException e) {
				logger.info("No language-specific file is available for " + filename + " so the default will be used.");
			}
		}
		if (contents == null) {
			try {
				subdirectory = "";
				filename = "/" + pkg  + "/" + subdirectory + topicName + ".txt";
				contents = Utilities.readFile(filename);
			} catch (IOException e) {
				logger.warning("Default topic initialization file " + filename + " could not be read", e);
				throw e;
			}
		}
		return contents;	
	}
}
